package com;

import com.amazonaws.services.s3.transfer.MyTransferManager;
import com.amazonaws.services.s3.transfer.MyTransferManagerBuilder;
import com.entity.PackCmd;
import com.handler.AuthorityHandler;
import com.handler.BucketHandler;
import com.handler.InvalidationHandler;
import com.handler.PackHandler;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemUtils;
import org.slf4j.LoggerFactory;
import picocli.CommandLine;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.List;
import java.util.Scanner;

public class Main {

    private static Scanner scanner;
    public static Scanner getScanner() {
        if (scanner == null) scanner = new Scanner(System.in);
        return scanner;
    }
    private final AwsUtils dataManage;
    private final CommandLine commandLine;
    private final PackCmd packCmd;

    public Main(String[] args) {
        this.dataManage = new AwsUtils(() -> {
            startFiles();
            return null;
        });
        Config.dataManage = this.dataManage;
        this.packCmd = this.dataManage.getPackCmd();
        commandLine = new CommandLine(this.packCmd);
//        args = new String[]{"-t", "2", "bname", "one-game"};
//        args = new String[]{"-cls", "-n", "onegame"};
//        args = new String[]{"-r", "D:\\projectPack\\uploadConfig\\test.txt"};
//        args = new String[]{"-cls"};
//        args = new String[]{"-help"};
        commandLine.execute(args);
    }

    /**
     * 开始执行更新上传
     */
    public void startFiles() {
        // 上传文件配置表
        File configFile;
        if (StringUtils.isNoneEmpty(this.packCmd.uploadFilePackFile)
                && (configFile = new File(this.packCmd.uploadFilePackFile)).exists()) {
            try {
                String content = FileUtils.readFileToString(configFile, "utf-8");
                this.commandLine.execute(content.split("\\s+"));
            } catch (Exception e) {
                System.err.println("执行配置表有问题, file=" + this.packCmd.uploadFilePackFile + " \n " + e.getMessage());
            }
            return;
        }
        // 如果有更新的文件 需要将他们单独打包到user目录
        if (this.packCmd.uploadFileList != null) {
            try {
                List<File> files = this.packCmd.uploadFileList;
                File file;
                File saveFile;
                File newPath = new File(FileUtils.getUserDirectoryPath(), this.packCmd.bucketName);
                if (newPath.exists()) FileUtils.deleteQuietly(newPath);
                newPath.mkdirs();
                for (int i = 0; i < files.size(); i++) {
                    file = files.get(i);
                    saveFile = new File(newPath, StringUtils.remove(changeDiskCharacter(file.getPath()),
                            changeDiskCharacter(this.packCmd.parentPath)));
                    FileUtils.copyFile(file, saveFile);
                }
                //   这里将目录弹出来  为了上传失败 可以手动复制传送
                if (SystemUtils.IS_OS_MAC) {
                    exec("open", newPath.getPath());
                } else if (SystemUtils.IS_OS_WINDOWS) {
                    exec("cmd.exe", "/c", "start", newPath.getPath());
                } else {
                    System.out.println("path = " + newPath.getPath());
                }
                System.out.println("将需要上传的文件打包到临时文件夹，并弹出成功!");
            } catch (Exception e) {
                System.err.println("要上传的文件配置表有问题, file=" + this.packCmd.uploadFileList + " \n " + e.getMessage());
                return;
            }
        }

        if (StringUtils.isNoneEmpty(this.packCmd.uploadFileConfig)
                && (configFile = new File(this.packCmd.uploadFileConfig)).exists()) {
            try {
                String content = FileUtils.readFileToString(configFile, "utf-8");
                this.commandLine.execute(content.split("\\s+"));
            } catch (Exception e) {
                System.err.println("上传文件配置表有问题, file=" + this.packCmd.uploadFileConfig + " \n " + e.getMessage());
            }
            return;
        }

        System.out.println("检测 登录用户");
        if (dataManage.checkAccount()) {
            System.out.println("error : accessKeyId=" + this.packCmd.accessKeyId + ", accessKeySecret=" + this.packCmd.accessKeySecret);
            return;
        }

        switch (this.packCmd.type) {
            case 1:// 打包
                new PackHandler(getMyTransferManager());
                break;
            case 2:// 创建桶
                if (StringUtils.isNotEmpty(this.packCmd.bucketName))
                    new BucketHandler(getMyTransferManager()).execute(this.packCmd.bucketName);
                else
                    System.out.println("不能执行创建 = bucketName=" + this.packCmd.bucketName);
                break;
            case 3:// 更改权限
                new AuthorityHandler(getMyTransferManager()).execute(this.packCmd.bucketName);
                break;
            default:
                if (this.packCmd.uploadFileList != null && this.packCmd.uploadFileList.size() > 0) {
                    new PackHandler(getMyTransferManager());
                } else {
                    if (!this.packCmd.clear)
                        System.out.println("未指定执行类型");
                }
                break;
        }

        // 程序最后执行 清除缓存任务
        System.out.println("OY");
        if (this.packCmd.clear) { // 需要清理
            System.out.println("开始清理服务器缓存");
            new InvalidationHandler();
        }

    }

    private MyTransferManager getMyTransferManager() {
        MyTransferManager transferManager = MyTransferManagerBuilder.standard()
                .withS3Client(AwsUtils.awsUtils.getS3Client())
                .build();
        System.out.println("成功连接AWS S3服务器。。。");
        return transferManager;
    }

    public static void main(String[] args) {
        System.setProperty("Log4jContextSelector", "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");
        System.setProperty("rootDir", getRunPath().getPath());
        LoggerFactory.getLogger(Main.class).info("启动 ");
        new Main(args);
    }









    /**
     * 获取运行路径
     *
     * @return
     */
    public static File getRunPath() {
        File file;
        URL jar = Main.class.getResource("Main.class");
        if (jar.getProtocol().equals("jar")) {
            URL url = Main.class.getProtectionDomain().getCodeSource().getLocation();
            try {
                String filePath = URLDecoder.decode(url.getPath(), "UTF-8");
//				System.out.println(filePath);
                if (filePath.endsWith(".jar")) {// 可执行jar包运行的结果里包含".jar"
                    // 截取路径中的jar包名
                    filePath = filePath.substring(0, filePath.lastIndexOf("/") + 1);
                }

                file = new File(filePath);
            } catch (UnsupportedEncodingException e) {
//			e.printStackTrace();
                LoggerFactory.getLogger(Main.class).error(e.getMessage());
                file = new File(System.getProperty("user.dir"));
            }
        } else {
            file = new File(System.getProperty("user.dir"));
        }
        return file;
    }

    /**
     * 执行一个文件
     *
     * @param command 命令
     */
    public void exec(String... command) {
        ProcessBuilder pb = new ProcessBuilder(command);
//		pb.directory(new File("cmd"));
        int runningStatus = 0;
        String s = null;
        try {
            Process p = pb.start();
            BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
            BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
            while ((s = stdInput.readLine()) != null) {
                if (s.length() > 3 && (s.startsWith("%n%") || s.startsWith("%pro%"))) {
                    System.out.print("\r");
                    System.out.print(s);
                } else {
                    System.out.println(s);
                }
            }
            while ((s = stdError.readLine()) != null) {
                System.err.println(s);
            }
            try {
                runningStatus = p.waitFor();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 转换盘符
     *
     * @param key
     * @return
     */
    public String changeDiskCharacter(String key) {
        return StringUtils.replace(key, "\\", "/");
    }


}
